// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat;

import java.io.File;

import com.eva.epc.common.util.PropertyMan;
import com.eva.framework.utils.LoggerFactory;
import com.x52im.rainbowchat.common.dto.AutoUpdateInfoFromServer;

/**
 * 用于执行客户端登陆请求时的客户端程序版本检查之用的实现类.
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 * @since 2.2
 */
public class ClientAPKVersionChecker
{
	/** 服务端的更新信息配置属性文件名 */
	public final static String APK_VERSION_PROPERTIES_FILE_NAME = "apk_version.properties";
	
	/** 配置属性之：版本号  */
	public final static String PROPERTIES_FIELD_VERSION = "version";
	/** 配置属性之：apk程序文件名  */
	public final static String PROPERTIES_FIELD_APK$FILE$NAME = "apk_name";
	/** 配置属性之：apk程序完整下载地址  */
	public final static String PROPERTIES_FIELD_APK$DOWNLOAD$URL = "apk_url";
	
	/** 
	 * 要提供给客户端更新之用的apk程序所放置的磁盘目录（注意：该目录末尾应包含斜线“/”）.
	 * 大名移动通中的，web项目的根目录(形如：d:/program../tomcat6/webapp/dmkxm1/)
	 * 就是apk程序的放置目录.*/
	private String apkDir = "";
	
	/**
	 * 构造方法.
	 * 
	 * @param _apkDir 要提供给客户端更新之用的apk程序所放置的磁盘目录（注意：该目录末尾应包含斜线“/”）.
	 * 在大名移动通中，web项目的根目录(形如：d:/program../tomcat6/webapp/dmkxm1/)
	 * 就是apk程序的放置目录.
	 */
	public ClientAPKVersionChecker(String _apkDir)
	{
		this.apkDir = _apkDir;
	}
	
	/**
	 * 据指定的客户端版本号与服务端当前最新版本号比较，并返回比较结果信息封装对象.
	 * 
	 * @param clientCurrentAPKVer 客户端登陆时提交上来的客户端程序版本号
	 * @return 包含需不需要更新等信息的dto
	 * @throws Exception
	 */
	public AutoUpdateInfoFromServer checkClientAPKVersion(String clientCurrentAPKVer)
		throws Exception
	{
		AutoUpdateInfoFromServer aui = new AutoUpdateInfoFromServer();
		//获得服务端配置好的当前最新客户端版本号
		String serverCurrentAPKVer = getServerCurrentAPKVer();
		//用客户端提交上来的版本与当前服务端的最新版比较，true表示客户端版本与服务端不一致（需要更新）
		boolean isClientNeedUpdate = isClientNeedUpdate(clientCurrentAPKVer, serverCurrentAPKVer);
		
		LoggerFactory.getLog().debug("<客户端版本检查> 客户端版本："+clientCurrentAPKVer+"，服务端版本："+serverCurrentAPKVer
				+"，客户端是否需要更新？"+isClientNeedUpdate);
		
		//如果需要更新则还需要取其它新版程序信息（稍后将返回给客户端由其完成程序更新）
		if(isClientNeedUpdate)
		{
			Object[] latestClientAPKInfo = getServerCurrentAPKInfo();
			//服务端当前新版程序大小（字节）
			long serverCurrentAPKFileSize = (Long)latestClientAPKInfo[0];
			//服务端当前新版程序的下载地址（完整的http地址，形如：http://crazyboy2011.xicp.net:4180/dmkx_mobi_a1_c.apk）
			String serverCurrentAPKURL = (String)latestClientAPKInfo[1];
			//设置需要更新标识
			aui.setNeedUpdate(true);
			aui.setLatestClientAPKVercionCode(serverCurrentAPKVer);
			aui.setLatestClientAPKFileSize(serverCurrentAPKFileSize);
			aui.setLatestClientAPKURL(serverCurrentAPKURL);
		}

		return aui;
	}
	
	/**
	 * 判断客户端需要否更新程序.
	 * 
	 * @param clientCurrentAPKVer 当前客户端版本号（由登陆的客户端程序提交上来的）
	 * @param serverCurrentAPKVer 当前服务端的最新版本号（服务端配置好的）
	 * @return
	 * @throws Exception
	 */
	public boolean isClientNeedUpdate(String clientCurrentAPKVer, String serverCurrentAPKVer)
		throws Exception
	{
		if(serverCurrentAPKVer == null || serverCurrentAPKVer.length() == 0)
			throw new RuntimeException("服务端没有设置当前允许的客户端APK" +
					"版本信息，请前往根目录下查看文件"+APK_VERSION_PROPERTIES_FILE_NAME);
		
		int serverCurrentAPKVerCode = Integer.parseInt(serverCurrentAPKVer);
		//客户端版本码为空或客户端版本码与服务端允许的最新版本不等则认为客户端需要更新
		if(clientCurrentAPKVer == null 
				|| serverCurrentAPKVerCode != Integer.parseInt(clientCurrentAPKVer))
			return true;
		return false;
	}
	
	/**
	 * 从更新信息配置文件里读取当前服务端的最新版本号.
	 * 
	 * @return 整数字符串
	 * @throws Exception
	 */
	public String getServerCurrentAPKVer() throws Exception
	{
		PropertyMan pm = getPropertyMan();
		String version = pm.getProperty(PROPERTIES_FIELD_VERSION);
		return version;
	}
	
	/**
	 * 返回更新信息配置属性文件的操作辅助对象.
	 * 
	 * @return
	 * @throws Exception
	 */
	public PropertyMan getPropertyMan() throws Exception
	{
		//取出部署后的web项目的classes磁盘路径（该配置文件位于../classes/直接目录下）
		String classedRootDiskPath = new File(PropertyMan.class.getResource("/").toURI()).getAbsolutePath();//不含末尾“/“
		String filePath = classedRootDiskPath + "/"+APK_VERSION_PROPERTIES_FILE_NAME;
		LoggerFactory.getLog().debug("<客户端版本检查> 配置文件路径："+filePath);
		return new PropertyMan(filePath);
	}
	
	/**
	 * 返回当前服务端存放的最新版本客户端程序信息.
	 * 包括：文件大小、完整下载地址.
	 * 
	 * @return 返回值是个2元素一维数组，元素0是文件大小（用于客户端下载时的进度提示之用）
	 * 、元素1是文件的完整下载http地址（用于客户端更新时读取该apk程序的地址）
	 * @throws Exception
	 */
	public Object[] getServerCurrentAPKInfo() throws Exception
	{
		PropertyMan pm = getPropertyMan();
		String apkFileName = pm.getProperty(PROPERTIES_FIELD_APK$FILE$NAME);
		//大名移动通中该APK文件位于web项目发布目录的根目录下
		String filePath = apkDir+apkFileName;//apk位于服务端的磁盘绝对路径
		String doawnloadURL = pm.getProperty(PROPERTIES_FIELD_APK$DOWNLOAD$URL)+"/"+apkFileName;//apk文件的完整http url下载地址
		File apkFile = new File(filePath);//apkDir已含末尾“/“
		LoggerFactory.getLog().debug("<客户端版本检查> apk文件路径："+filePath
				+"，文件大小："+apkFile.length()+"，下载地址："+doawnloadURL);
		return new Object[]{apkFile.length(), doawnloadURL};
	}
}
